package com.mrd.frame.controller;

import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.concurrent.TimeUnit;

import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;
import org.jdom2.JDOMException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import com.alibaba.fastjson.JSONObject;
import com.mrd.base.utils.JsonUtils;
import com.mrd.frame.attachment.AttachmentService;
import com.mrd.frame.domain.AccessConfig;
import com.mrd.frame.domain.NoticeMessage;
import com.mrd.frame.domain.Order;
import com.mrd.frame.domain.OrderInteraction;
import com.mrd.frame.domain.PayConfig;
import com.mrd.frame.domain.TradeStatement;
import com.mrd.frame.domain.message.PayMessage;
import com.mrd.frame.domain.message.ReconciliationMessage;
import com.mrd.frame.domain.message.RefundMessage;
import com.mrd.frame.domain.params.PayParams;
import com.mrd.frame.domain.params.ReconciliationParams;
import com.mrd.frame.domain.params.RefundParams;
import com.mrd.frame.onlinepay.notify.AliNotify;
import com.mrd.frame.onlinepay.notify.AliNotifyParam;
import com.mrd.frame.onlinepay.pay.impl.Alipay;
import com.mrd.frame.onlinepay.pay.impl.WxPlay;
import com.mrd.frame.onlinepay.query.impl.AliQuery;
import com.mrd.frame.onlinepay.query.impl.WxQuery;
import com.mrd.frame.onlinepay.refund.impl.AliRefund;
import com.mrd.frame.onlinepay.refund.impl.WxRefund;
import com.mrd.frame.redis.JedisClientClusterImpl;
import com.mrd.frame.remote.Validate;
import com.mrd.frame.service.AccessConfigService;
import com.mrd.frame.service.OrderInteractionService;
import com.mrd.frame.service.OrderService;
import com.mrd.frame.service.TradeStatementService;
import com.mrd.weixinpay.util.ChangeUtil;
import com.mrd.weixinpay.util.Constents;
import com.mrd.weixinpay.util.HttpUtil;
import com.mrd.weixinpay.util.PayCommonUtil;
import com.mrd.weixinpay.util.XMLUtil;

/**
 * @author AllisonWang 此类实现扫码原生支付模式二的功能。
 */

@RequestMapping("/payControl")
@Controller
public class SweepPaymentAction {
	private static final Logger logger = Logger
			.getLogger(SweepPaymentAction.class);
	@Autowired
	private OrderInteractionService orderInteractionService;
	@Autowired
	private OrderService orderService;
	private static ChangeUtil changeUtil;
	@Autowired
	private Validate validate;
	@Autowired
	private AccessConfigService accessConfigService;
	@Autowired
	private WxPlay	            wxPlay;
	@Autowired
	private TradeStatementService tradeStatementService;
	@Autowired
	private WxRefund	        wxRefund;
	@Autowired
	private Alipay alipay;
	@Autowired
	private AliRefund aliRefund;
	@Autowired
	private AliNotify aliNotify;
	@Autowired
	private WxQuery wxQuery;
	@Autowired
	private AliQuery aliQuery;
	@Autowired
	private JedisClientClusterImpl jedisClientClusterImpl;
    @Autowired
    private AttachmentService attachmentService;
    
	/**
	 * 统一下单接口：1，系统根据业务系统返回的信息生成预下单，2，反馈微信返回的url传入业务系统，以便业务系统生成二维码；或者将错误信息传入业务系统。
	 * 后期根据需求此方法做出相应修改。
	 * 
	 * @param orderId
	 * @param orderName
	 * @param orderPrice
	 * @return
	 * @throws JDOMException
	 * @throws IOException
	 */
	// 和业务系统对接时使用以下请求参数
	@RequestMapping("/unifiedOrder")
	@ResponseBody
	public PayMessage unifiedOrder(@ModelAttribute PayParams payParams,
			HttpServletRequest request, HttpServletResponse repose)
			throws JDOMException, IOException,Exception {
		// ---- 使用明睿达测试号时的配置信息结束
		// 正式开发。 1，解析客户端的数据，存储到请求交互情况记录表中order_interactions，
		// 2，验证通过向微信发起支付请求，微信回应后生成二维码存储到系统中并将二维码的保存路径给业务系统，验证不通过，返回不通过的原因给业务系统

		OrderInteraction orderInt = new OrderInteraction();
		// // orderInt.setOrderId(payParams.getOutTradeNo());
		orderInt.setCreateTime(new Date());
		orderInt.setOrderInteractionId(String.valueOf(System
				.currentTimeMillis()));
		orderInt.setStatus("0");
		orderInt.setType("A1");
		orderInt.setParameters(payParams.getBody() + ","
				+ payParams.getOutTradeNo() + "," + payParams.getUserKey()
				+ "," + payParams.getPayChannel() + "," + payParams.getSign()
				+ "," + payParams.getSubject() + "," + payParams.getTimeStart()
				+ "," + payParams.getTotalAmount() + ","
				+ payParams.getTradeType());

		Order order = new Order();
		PayMessage payMessage = new PayMessage();

		// 验证

		Order valretOrd = validate.checkTradeNo(payParams.getUserKey(),
				payParams.getOutTradeNo());
		String valMsg = validate.validateRequest(request, payParams, valretOrd);
		AccessConfig accessConfig = new AccessConfig();
		accessConfig = accessConfigService.selectByUserKeyAndPayChannel(
				payParams.getUserKey(),
				String.valueOf(payParams.getPayChannel()));
		if ("PASS".equals(valMsg)) {
			// 向第三方发送支付请求
			// status 订单状态 0：处理失败，1：进行中，2：完成，3：超时,4:验证不通过
			if (valretOrd==null ||(valretOrd.getStatus() == null || "".equals(valretOrd
					.getStatus()))
					|| ((valretOrd != null && !"".equals(valretOrd)) && ("0"
							.equals(valretOrd.getStatus())
							|| "3".equals(valretOrd.getStatus()) || "4"
								.equals(valretOrd.getStatus())))) {

				Map weixinPayRest = new HashMap<>();
				String newreq = "";
				int reqTimes = 2;// 请求次数，目前默认2次，后期再根据实际配置情况处理
				// 微信支付
				int reqTimesOver = 1;// 目前已经完成的请求次数

				// 存入请求交互记录表中, 客户端请求支付
				// orderInt.setOrderId(orderId);
				// Integer a1 = orderInteractionService.insert(orderInt);

				do {
					if ("1".equals(payParams.getPayChannel())) {
						weixinPayRest = wxPlay.pay(accessConfig, payParams,
								order, orderInt, payMessage, orderService,
								orderInteractionService);
					} else if ("2".equals(payParams.getPayChannel())) {
						weixinPayRest = alipay.pay(accessConfig, payParams,
								order, orderInt, payMessage, orderService,
								orderInteractionService);
					}

					newreq = (String) weixinPayRest.get("newRequest");
					orderInt.setParameters(String.valueOf(weixinPayRest
							.get("retresXML")));
					payMessage = (PayMessage) weixinPayRest.get("payMessage");
					if ("NO".equals(newreq)) {
						break;
					}
					reqTimesOver += 1;

				} while ("YES".equals(newreq) && (reqTimesOver < reqTimes));
				payMessage = (PayMessage) weixinPayRest.get("payMessage");
//				printResultToSystem(repose, payMessage, orderInt);

			} else if ((valretOrd.getStatus() != null && !"".equals(valretOrd
					.getStatus())) && ("2".equals(valretOrd.getStatus()))) {
				// 支付已完成直接返回给客户端,并将客户端请求参数信息记录到交互表中
				orderInt.setOrderId(valretOrd.getOrderId());
				int a1 = orderInteractionService.insert(orderInt);

				payMessage.setOutTradeNo(payParams.getOutTradeNo());
				payMessage.setCode(Integer.parseInt("1"));
				payMessage.setSign(payParams.getSign());
				payMessage.setResultCode("SUCCESS");
				payMessage.setReturnCode("SUCCESS");
				payMessage.setMessage(Constents.SUCCESMESSAGE);
				payMessage.setReturnMsg("支付完成！");
				payMessage.setTradeType(payParams.getTradeType());

				orderInt.setOrderInteractionId(String.valueOf(System
						.currentTimeMillis()));
				orderInt.setCreateTime(new Date());
				orderInt.setType("A4");

//				printResultToSystem(repose, payMessage, orderInt);
			} else if ((valretOrd != null && !"".equals(valretOrd))
					&& ("1".equals(valretOrd.getStatus()))) {
				// 交易进行中，向第三方发起查询交易，按照查询结果再返回信息给第三方,并将客户端请求存到交互表中
				orderInt.setOrderId(valretOrd.getOrderId());
				int a1 = orderInteractionService.insert(orderInt);

				Map queryResult = new HashMap();
				if ("1".equals(payParams.getPayChannel())) {
					// 微信查询
					queryResult = wxQuery.queryOrder(payParams, accessConfig, valretOrd);
				} else if ("2".equals(payParams.getPayChannel())) {
					// 支付宝查询
					queryResult = aliQuery.queryOrder(payParams, accessConfig, valretOrd);
				}
				payMessage.setOutTradeNo(payParams.getOutTradeNo());
				payMessage.setCode(Integer.parseInt("1"));
				payMessage.setSign(payParams.getSign());
				payMessage.setResultCode((String) queryResult.get("retRsult"));
				payMessage.setReturnCode("SUCCESS");
				payMessage.setReturnMsg((String) queryResult.get("reMsg"));
				payMessage.setTradeType(payParams.getTradeType());
				payMessage.setQrUrl(valretOrd.getQrUrl());

				orderInt.setOrderInteractionId(String.valueOf(System
						.currentTimeMillis()));
				orderInt.setCreateTime(new Date());
				orderInt.setType("A4");

//				printResultToSystem(repose, payMessage, orderInt);
			}

		} else {
			// 生成订单表并将状态置为验证不通过，存客户端请求到交互表
			order.setOrderId(String.valueOf(System.currentTimeMillis()));
			order.setPayChannel(payParams.getPayChannel());
			order.setPayType("NATIVE");
			order.setStatus("4");
			order.setTradeNo(payParams.getOutTradeNo());
			order.setTimeStart(new Date());
			order.setTotalAmount(Integer.parseInt(payParams.getTotalAmount()));
			order.setTradeType("1");
			order.setUserKey(payParams.getUserKey());
			Integer r1 = orderService.insert(order);

			orderInt.setOrderId(order.getOrderId());
			orderInt.setStatus("0");
			int a1 = orderInteractionService.insert(orderInt);

			payMessage.setReturnMsg(valMsg);
			payMessage.setOutTradeNo(payParams.getOutTradeNo());
			payMessage.setSign(payParams.getSign());
			payMessage.setTradeType(payParams.getTradeType());
			payMessage.setMessage(Constents.FAULTMESSAGE);

			orderInt.setOrderInteractionId(String.valueOf(System
					.currentTimeMillis()));
			orderInt.setCreateTime(new Date());
			orderInt.setType("A4");
//			printResultToSystem(repose, payMessage, orderInt);
		}
		return payMessage;
	}

	// 回调响应微信通知
	@RequestMapping("/weixinNotify")
	public void weixinNotify(HttpServletRequest request,
			HttpServletResponse response) throws Exception {
		String out_trade_no = "";
		try {
			// 读取参数
			InputStream inputStream;
			StringBuffer sb = new StringBuffer();
			inputStream = request.getInputStream();
			String s;
			BufferedReader in = new BufferedReader(new InputStreamReader(
					inputStream, "UTF-8"));
			while ((s = in.readLine()) != null) {
				sb.append(s);
			}
			in.close();
			inputStream.close();
			logger.info("微信回调返回信息：" + sb);
			System.out.println("微信回调返回信息：" + sb);
			// 解析xml成map
			Map<String, String> m = new HashMap<String, String>();
			m = XMLUtil.doXMLParse(sb.toString());

			// 过滤空 设置 TreeMap
			SortedMap<Object, Object> packageParams = new TreeMap<Object, Object>();
			Iterator it = m.keySet().iterator();
			while (it.hasNext()) {
				String parameter = (String) it.next();
				String parameterValue = m.get(parameter);

				String v = "";
				if (null != parameterValue) {
					v = parameterValue.trim();
				}
				packageParams.put(parameter, v);
			}

			// 账号信息
			String key = "";

			logger.info(packageParams);

			Order order = new Order();
			String orderId = (String) packageParams.get("out_trade_no");// 支付平台为商家生成的新的发送给微信请求支付的订单号
			order = orderService.selectByPrimaryKey(orderId);
			AccessConfig accessConfig = accessConfigService
					.selectByUserKeyAndPayChannel(order.getUserKey(),
							order.getPayChannel());
			key = accessConfig.getPrivateKey();
			TradeStatement tradeStatement = new TradeStatement();
			OrderInteraction orderInter = new OrderInteraction();

			String mch_id = (String) packageParams.get("mch_id");
			out_trade_no = orderId;
			String transaction_id = (String) packageParams
					.get("transaction_id");// 微信支付订单号
			String outTradeNo = order.getTradeNo();// 商家订单号
			String total_fee = (String) packageParams.get("total_fee");// 支付订单金额
			String time_end = (String) packageParams.get("time_end");

			logger.info("签名结果："+PayCommonUtil.isTenpaySign("UTF-8", packageParams, key));
			logger.info("金额结果："+(order.getTotalAmount()==Integer.parseInt(total_fee)));
			// 判断签名是否正确,判断返回的金额是否和订单中的一致
			if (PayCommonUtil.isTenpaySign("UTF-8", packageParams, key)
					&& order.getTotalAmount()==Integer.parseInt(total_fee)) {
				String resXml = "";
				if ("SUCCESS".equals((String) packageParams.get("result_code"))) {
					// 更新订单表中的订单状态，通知而业务系统,将此信息存入资金流水表，将此信息存入交互记录表
					SimpleDateFormat formate = new SimpleDateFormat(
							"yyyyMMddHHmmss");
					Date date = formate.parse(time_end);

					// 更新订单表
					if (!"2".equals(order.getStatus())) {
						order.setStatus("2");
						order.setThirdOrderId(transaction_id);
						orderService.updateByPrimaryKeySelective(order);
					}

					// 存入资金流水表
					tradeStatement.setOrderId(orderId);
					List<TradeStatement> trade = new ArrayList<>();
					trade = tradeStatementService
							.selectSelective(tradeStatement);
					if (!(trade.size() > 0)) {
						tradeStatement.setOrderId(orderId);
						tradeStatement.setPayChannel("1");
						tradeStatement.setThirdOrderId(transaction_id);
						tradeStatement.setTotalAmount(Integer
								.parseInt(total_fee));
						tradeStatement.setTradeNo(outTradeNo);
						tradeStatement.setTradeTime(date);
						tradeStatement.setTradeType("1");
						tradeStatement.setTradingStatementsId(String
								.valueOf(System.currentTimeMillis()));
						tradeStatement.setUserKey(order.getUserKey());
						tradeStatementService.insert(tradeStatement);

					}

					// 将第三方返回给服务端的信息存入交互记录表
					orderInter.setOrderId(orderId);
					orderInter.setType("A5");
					List<OrderInteraction> ordeInts = new ArrayList<>();
					ordeInts = orderInteractionService
							.selectSelective(orderInter);
					if (ordeInts==null) {
						orderInter.setCreateTime(new Date());
						orderInter.setOrderInteractionId(String.valueOf(System
								.currentTimeMillis()));
						orderInter.setParameters(sb.toString());
						orderInter.setStatus("0");
						int a5 = orderInteractionService.insert(orderInter);
					}

					// A7：server给client的支付结果， A8：client给server的收到支付结果反馈，
					OrderInteraction ordInt = new OrderInteraction();
					ordInt.setOrderId(orderId);
					ordInt.setType("A8");
					ordInt.setStatus("0");
					List<OrderInteraction> ordInts = new ArrayList<>();
					if (ordInts!=null) {
						Map<String, Object> map = new HashMap<>();
						map.put("orderId", orderId);
						map.put("time_end", time_end);
						map.put("transaction_id", transaction_id);
						map.put("outTradeNo", outTradeNo);
						map.put("total_fee", total_fee);
						map.put("status", "SUCCESS");
						JSONObject json = new JSONObject(map);
						String retStatus = "FAILURE";
						try {
							retStatus = HttpUtil.postData(
									accessConfig.getNotifyUrl(),
									json.toString(), "application/json");

							// 服务端发送回调信息给业务系统存入交互表中
							ordInt.setCreateTime(new Date());
							ordInt.setOrderInteractionId(String.valueOf(System
									.currentTimeMillis()));
							ordInt.setStatus("0");
							ordInt.setType("A7");
							ordInt.setParameters(json.toString());
							int a7 = orderInteractionService.insert(ordInt);

							if ("SUCCESS".equals(retStatus)) {
								// 客户端返回成功信息存储到交互记录表
								ordInt.setCreateTime(new Date());
								ordInt.setOrderInteractionId(String
										.valueOf(System.currentTimeMillis()));
								ordInt.setParameters(retStatus);
							} else {
								// 客户端反馈不成功，此时进行标记以便后续消息重发
								NoticeMessage noticeMsg = new NoticeMessage( orderId, time_end, "", outTradeNo,
										 total_fee, "SUCCESS", order.getUserKey(), accessConfig.getNotifyUrl());
								jedisClientClusterImpl.set(Constents.PAYNOTICEINDEX+noticeMsg.getOrderId(), noticeMsg, new Long(120), TimeUnit.MINUTES);
								ordInt.setCreateTime(new Date());
								ordInt.setOrderInteractionId(String
										.valueOf(System.currentTimeMillis()));
								ordInt.setParameters(retStatus);
								ordInt.setStatus("1");
							}
							int a8 = orderInteractionService.insert(ordInt);
						} catch (Exception e) {

						} finally {
							// 服务端向业务系统推送支付结果失败,需要重发
							ordInt.setCreateTime(new Date());
							ordInt.setOrderInteractionId(String.valueOf(System
									.currentTimeMillis()));
							ordInt.setStatus("1");
							ordInt.setType("A7");
							ordInt.setParameters(json.toString());

						}

					}
					
	    			//清理对应的图片
	    			attachmentService.delete(order.getOrderId());
	    			
					logger.info("支付成功");
					// 通知微信.异步确认成功.必写.不然会一直通知后台.八次之后就认为交易失败了.
					resXml = "<xml>"
							+ "<return_code><![CDATA[SUCCESS]]></return_code>"
							+ "<return_msg><![CDATA[OK]]></return_msg>"
							+ "</xml> ";

				} else {
					// TODO 吊起查询接口,将支付失败的信息通知给业务系统,将此信息存入交互记录表,
					Map retQueryMap = wxQuery.queryOrder(null, accessConfig, order);
					Order retOrder = (Order) retQueryMap.get("reOrder");
					Map<String, Object> map = new HashMap<>();
					map.put("orderId", orderId);
					map.put("time_end", time_end);
					map.put("transaction_id", transaction_id);
					map.put("outTradeNo", outTradeNo);
					map.put("total_fee", total_fee);

					if ("2".equals(retOrder.getStatus())) {
						// 此订单完成支付
						map.put("status", "FAIL");
					} else {
						map.put("status", "FAIL");
					}
					JSONObject json = new JSONObject(map);
					// 发送信息给业务系统
					OrderInteraction ordInt = new OrderInteraction();
					String retStatus = "FAILURE";
					try {
						retStatus = HttpUtil.postData(
								accessConfig.getNotifyUrl(), json.toString(),
								"application/json");

						// 服务端发送回调信息给业务系统存入交互表中
						ordInt.setCreateTime(new Date());
						ordInt.setOrderInteractionId(String.valueOf(System
								.currentTimeMillis()));
						ordInt.setStatus("0");
						ordInt.setType("A7");
						ordInt.setParameters(json.toString());
						int a7 = orderInteractionService.insert(ordInt);

						if ("SUCCESS".equals(retStatus)) {
							// 客户端返回成功信息存储到交互记录表
							ordInt.setCreateTime(new Date());
							ordInt.setOrderInteractionId(String.valueOf(System
									.currentTimeMillis()));
							ordInt.setParameters(retStatus);
						} else {
							NoticeMessage noticeMsg = new NoticeMessage( orderId, time_end, "", outTradeNo,
									 total_fee, retStatus, order.getUserKey(), accessConfig.getNotifyUrl());
							jedisClientClusterImpl.set(Constents.PAYNOTICEINDEX+noticeMsg.getOrderId(), noticeMsg, new Long(120), TimeUnit.MINUTES);
							// 客户端反馈不成功，此时进行标记以便后续消息重发
							ordInt.setCreateTime(new Date());
							ordInt.setOrderInteractionId(String.valueOf(System
									.currentTimeMillis()));
							ordInt.setParameters(retStatus);
							ordInt.setStatus("1");
						}
						int a8 = orderInteractionService.insert(ordInt);
					} catch (Exception e) {

					} finally {
						// 服务端向业务系统推送支付结果失败,需要重发
						ordInt.setCreateTime(new Date());
						ordInt.setOrderInteractionId(String.valueOf(System
								.currentTimeMillis()));
						ordInt.setStatus("1");
						ordInt.setType("A7");
						ordInt.setParameters(json.toString());

					}
					orderInter.setCreateTime(new Date());
					orderInter.setOrderInteractionId(String.valueOf(System
							.currentTimeMillis()));
					orderInter.setStatus("0");
					orderInter.setType("A6");
					orderInter.setParameters(new JSONObject(map).toString());
					int a6 = orderInteractionService.insert(orderInter);

					logger.info("支付失败,错误信息：" + packageParams.get("err_code"));
					resXml = "<xml>"
							+ "<return_code><![CDATA[FAIL]]></return_code>"
							+ "<return_msg><![CDATA[报文为空]]></return_msg>"
							+ "</xml> ";

				}
				// ------------------------------
				// 处理业务完毕
				// ------------------------------
				BufferedOutputStream out = new BufferedOutputStream(
						response.getOutputStream());
				out.write(resXml.getBytes());
				out.flush();
				out.close();
			} else {
				// 不需要做处理，等待微信再次通知
				logger.info("通知签名验证失败");
			}

		} catch (IOException e) {
			logger.error("Error connecting to " + e.getMessage());
		} finally {
			OrderInteraction orderIdter = new OrderInteraction();
			orderIdter.setCreateTime(new Date());
			orderIdter.setOrderInteractionId(String.valueOf(System
					.currentTimeMillis()));
			orderIdter.setStatus("1");
			orderIdter.setType("A6");
			orderIdter.setOrderId(out_trade_no);
			// orderIdter.setParameters();
			int a6 = orderInteractionService.insert(orderIdter);

		}
	}

	/**
	 * 回调响应支付宝通知
	 * @author han
	 * @param aliNotifyParam
	 * @param request
	 * @param response
	 */
	@RequestMapping("/alipayNotify")
	public void aliNotify(HttpServletRequest request, HttpServletResponse response) {
		logger.info("支付宝回掉通知~~~~~~~~~~~~~~");
		try {
			Map<String, String[]> requestParams = request.getParameterMap();
			String message = aliNotify.excute(orderService,
					tradeStatementService, orderInteractionService,
					accessConfigService, requestParams);
			BufferedOutputStream out = new BufferedOutputStream(
					response.getOutputStream());
			out.write(message.getBytes());
			out.flush();
			out.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 申请退款接口
	 * 当交易发生之后一段时间内，由于买家或者卖家的原因需要退款时，卖家可以通过退款接口将支付款退还给买家，微信支付将在收到退款请求并且验证成功之后
	 * ，按照退款规则将支付款按原路退到买家帐号上。 注意： 1、交易时间超过一年的订单无法提交退款；
	 * 2、微信支付退款支持单笔交易分多次退款，多次退款需要提交原支付订单的商户订单号和设置不同的退款单号。总退款金额不能超过用户实际支付金额。
	 * 一笔退款失败后重新提交，请不要更换退款单号，请使用原商户退款单号。 已经结算的订单使用此接口无法进行退款，因此需要登录商户后台进行退款。
	 * 
	 * @param request
	 * @param response
	 * @return
	 */
	@RequestMapping("/requestRefund")
	@ResponseBody
	public RefundMessage requestRefund(@ModelAttribute RefundParams refParams,
	        HttpServletRequest request,
			HttpServletResponse response) {
		// 整理业务系统传递的参数
		// B1：client向server的退款请求， B2：server向第三方的退款请求， B3：第三方给server的退款结果，
		// B4：server给client的退款结果，
		OrderInteraction orderInt = new OrderInteraction();
		orderInt.setCreateTime(new Date());
		orderInt.setOrderInteractionId(String.valueOf(System
				.currentTimeMillis()));
		orderInt.setType("B1");
		orderInt.setParameters(refParams.getRefundReason() + ","
				+ refParams.getOutTradeNo() + "," + refParams.getUserKey()
				+ "," + refParams.getPayChannel() + "," + refParams.getSign()
				+ "," + refParams.getRefundAmount() + ","
				+ refParams.getTimeStart() + "," + refParams.getTotalAmount()
				+ "," + refParams.getOutRefundNo());

		Order order = new Order();
		PayMessage payMessage = new PayMessage();
		RefundMessage retRefundMessage = new RefundMessage();

		// 验证
		Order valretOrd = validate.checkTradeNo(refParams.getUserKey(),
				refParams.getOutRefundNo());
		String valMsg = validate.validateRequest(request, refParams, valretOrd);
		AccessConfig accessConfig = new AccessConfig();
		accessConfig = accessConfigService.selectByUserKeyAndPayChannel(
				refParams.getUserKey(),
				String.valueOf(refParams.getPayChannel()));

		//获取关联支付流水
		TradeStatement payStatement = new TradeStatement();
		payStatement.setTradeNo(refParams.getOutTradeNo());
		payStatement.setUserKey(refParams.getUserKey());
		payStatement = tradeStatementService.selectSelective(payStatement).get(0);
		// 验证通过
		if ("PASS".equals(valMsg)) {

			// 进行退款处理: status 订单状态 0：处理失败(此时需要使用原来退款单号进行退款处理)，
			// 1：进行中（使用新的单号向第三方发起支付请求），2：完成（重复请求退款），4:验证不通过，“” 新的退款请求

			if (valretOrd == null || "".equals(valretOrd.getStatus())
					|| valretOrd.getStatus() == null
					|| "1".equals(valretOrd.getStatus())
					|| "0".equals(valretOrd.getStatus())) {
				// 按照新的退款请求处理
				if (!"0".equals(valretOrd.getStatus())) {
					// 生成退款订单
					order.setOrderId(String.valueOf(System
							.currentTimeMillis()));
					order.setPayChannel("1");
					order.setTradeNo(refParams.getOutRefundNo());
					order.setTimeStart(new Date());
					order.setTotalAmount(refParams.getRefundAmount());// 商户退款单号
					order.setTradeType("2");
					order.setUserKey(refParams.getUserKey());
					order.setPayType("NATIVE");
					order.setRelatedTradeNo(refParams.getOutTradeNo());// 商户支付单号
					order.setStatus("1");
					Integer r1 = orderService.insert(order);
				} else {
					// 第三方退款失败的订单，使用原来的退款单号进行退款
					order = valretOrd;
					
				}
				
				// 判断是支付宝还是微信
				if ("1".equals(refParams.getPayChannel())) {
					
					RefundMessage refundMsg = (RefundMessage) wxRefund
							.refund(response, orderInt,
									orderInteractionService, accessConfig,
									order, payStatement, refParams, orderService,
									tradeStatementService);

					retRefundMessage = refundMsg;
					// 响应客户端的退款请求
					// try {
					// printRefunResultToSystem(response, refundMsg,
					// orderInt);
					// } catch (IOException e) {
					// e.printStackTrace();
					// }
					
				} else {
					// 支付宝退款
					RefundMessage refundMsg = (RefundMessage) aliRefund
							.refund(response, orderInt,
									orderInteractionService, accessConfig,
									order, payStatement, refParams, orderService,
									tradeStatementService);

					retRefundMessage = refundMsg;

					// // 响应客户端的退款请求
					// try {
					// printRefunResultToSystem(response, refundMsg,
					// orderInt);
					// } catch (IOException e) {
					// e.printStackTrace();
					// }
				}

				
			} else if ("2".equals(valretOrd.getStatus())) {
				// status 订单状态 2 退款已完成 属于重复的退款申请，直接告知业务系统，并记录信息到交互表
				// 封装返回给客户端的信息
				RefundMessage refundMsg = new RefundMessage();
				refundMsg.setOutRefundNo(refParams.getOutRefundNo());// 商户退款单号
				refundMsg.setOutTradeNo(refParams.getOutTradeNo());// 商户订单号
				refundMsg.setCode(Integer.parseInt("0"));// 请求失败
				refundMsg.setFundChange("N");// 资金未发生变化
				refundMsg.setMessage(Constents.FAULTMESSAGE);// 请求信息反馈
				refundMsg.setOrderId(payStatement.getOrderId());// 平台支付单号
				refundMsg.setResultCode("FAIL");// 返回代码
				refundMsg.setReturnCode("FAIL");// 返回代码
				refundMsg.setReturnMsg("此笔退款已完成，请不要重复提交退款申请!");// 第三方返回错误提示信息
				refundMsg.setSign(refParams.getSign());// 签名
				refundMsg.setTotalAmount(valretOrd.getTotalAmount());// 订单总金额
				
				// try {
				// printRefunResultToSystem(response, refundMsg, orderInt);
				// } catch (IOException e) {
				// e.printStackTrace();
				// }
				retRefundMessage = refundMsg;
			}
			/*
			if (ords.size() > 0) {
			} else {
			// 订单已完成支付,可以进行退款流程
				// 订单未完成支付，直接返回给业务系统，生成退款请求订单、将客户端的退款请求记录到交互表
				// 生成退款订单
				order.setOrderId(String.valueOf(System.currentTimeMillis()));
				order.setPayChannel("1");
				order.setTradeNo(refParams.getOutRefundNo());
				order.setTimeStart(new Date());
				order.setTotalAmount(refParams.getRefundAmount());// 商户退款单号
				order.setTradeType("2");
				order.setUserKey(refParams.getUserKey());
				order.setPayType("NATIVE");
				order.setRelatedTradeNo(refParams.getOutTradeNo());// 商户支付单号
				order.setStatus("1");
				Integer r1 = orderService.insert(order);

				// 将客户端向服务端发起的退款请求存入交互表中
				orderInt.setOrderId(order.getOrderId());
				orderInt.setType("B1");
				orderInt.setStatus("0");
				int b1 = orderInteractionService.insert(orderInt);

				// 封装返回给客户端的信息
				RefundMessage refundMsg = new RefundMessage();
				refundMsg.setOutRefundNo(refParams.getOutRefundNo());// 商户退款单号
				refundMsg.setOutTradeNo(refParams.getOutTradeNo());// 商户订单号
				refundMsg.setCode(Integer.parseInt("0"));// 请求失败
				refundMsg.setFundChange("N");// 资金未发生变化
				refundMsg.setMessage(Constents.FAULTMESSAGE);// 请求信息反馈
				refundMsg.setOrderId(ords.get(0).getOrderId());// 平台支付单号
				refundMsg.setResultCode("FAIL");// 返回代码
				refundMsg.setReturnCode("FAIL");// 返回代码
				refundMsg.setReturnMsg("此笔订单尚未完成支付，不能进行退款，请稍后重试");// 第三方返回错误提示信息
				refundMsg.setSign(refParams.getSign());// 签名
				refundMsg.setTotalAmount(valretOrd.getTotalAmount());// 订单总金额

				try {
					printRefunResultToSystem(response, refundMsg, orderInt);
				} catch (IOException e) {
					e.printStackTrace();
				}

			}*/

		} else {
			// 验证未通过 生成退款请求订单，将客户端请求记录到交货表，返回信息给业务系统
			// 生成退款订单
			order.setOrderId(String.valueOf(System.currentTimeMillis()));
			order.setPayChannel("1");
			order.setTradeNo(refParams.getOutRefundNo());
			order.setTimeStart(new Date());
			order.setTotalAmount(refParams.getRefundAmount());// 商户退款单号
			order.setTradeType("2");
			order.setUserKey(refParams.getUserKey());
			order.setPayType("NATIVE");
			order.setRelatedTradeNo(refParams.getOutTradeNo());// 商户支付单号
			order.setStatus("4");
			Integer r1 = orderService.insert(order);

			// 将客户端向服务端发起的退款请求存入交互表中
			orderInt.setOrderId(order.getOrderId());
			orderInt.setType("B1");
			orderInt.setStatus("0");
			int b1 = orderInteractionService.insert(orderInt);

			// 封装返回给客户端的信息
			RefundMessage refundMsg = new RefundMessage();
			refundMsg.setOutRefundNo(refParams.getOutRefundNo());// 商户退款单号
			refundMsg.setOutTradeNo(refParams.getOutTradeNo());// 商户订单号
			refundMsg.setCode(Integer.parseInt("0"));// 请求失败
			refundMsg.setFundChange("N");// 资金未发生变化
			refundMsg.setMessage(Constents.FAULTMESSAGE);// 请求信息反馈
			refundMsg.setOrderId(order.getOrderId());// 平台支付单号
			refundMsg.setResultCode("FAIL");// 返回代码
			refundMsg.setReturnCode("FAIL");// 返回代码
			refundMsg.setReturnMsg("验证失败，失败信息如下：" + valMsg);// 第三方返回错误提示信息
			refundMsg.setSign(refParams.getSign());// 签名
			refundMsg.setTotalAmount(valretOrd.getTotalAmount());// 订单总金额
			retRefundMessage = refundMsg;
			// try {
			// printRefunResultToSystem(response, refundMsg, orderInt);
			// } catch (IOException e) {
			// e.printStackTrace();
			// }

		}
		return retRefundMessage;

	}
	
	/**
	 * 对账接口
	 * @param params
	 * @return
	 */
	@RequestMapping(value = "/findStatementByTradeNo", method = RequestMethod.POST)
	@ResponseBody
	public ReconciliationMessage reconciliation(ReconciliationParams params){
		//记录交互记录
		orderInteractionService.insert(new OrderInteraction(null,"C1",JsonUtils.objectToJson(params)));
		ReconciliationMessage rm = new ReconciliationMessage();
		String msg = validate.checkParams(params);
		if(msg == null){
			try {
				rm = tradeStatementService.reconciliation(params);
			} catch (Exception e) {
				e.printStackTrace();
				rm.setCode(-1);
				rm.setMessage("对账单获取失败");
				logger.error("对账单获取失败", e);
			}
		} else {
			rm.setCode(-1);
			rm.setMessage(msg);
		}
		//记录交互记录
		orderInteractionService.insert(new OrderInteraction(null,"C2",JsonUtils.objectToJson(rm)));
		return rm;
	}
	
	/**
	 * 将数据封装后传回给业务系统,返回查询类的信息。
	 * 
	 * @param response
	 * @param orderInt
	 * @param map
	 * @throws IOException
	 */
	public void printResultToSystem(ServletResponse response, Object obj,
			OrderInteraction orderInt) throws IOException {
		try {
			response.setContentType("text/html;charset=utf-8");
			response.setCharacterEncoding("utf-8");
			PrintWriter out = response.getWriter();
			out.print(obj);
			out.flush();
			out.close();
//			orderInt.setStatus("0");
//			orderInt.setOrderInteractionId(String.valueOf(System
//					.currentTimeMillis()));
//			orderInt.setCreateTime(new Date());
//			orderInt.setType("A4");
//			int oi1 = orderInteractionService.insert(orderInt);
		} catch (Exception e) {
			orderInt.setOrderInteractionId(String.valueOf(System
					.currentTimeMillis()));
			orderInt.setCreateTime(new Date());
			orderInt.setStatus("1");
			orderInt.setType("A4");
			int oi2 = orderInteractionService.insert(orderInt);
		}

	}

	/**
	 * 响应第三方的退款请求
	 * 
	 * @param response
	 * @param obj
	 * @param orderInt
	 * @throws IOException
	 */
	public void printRefunResultToSystem(ServletResponse response, Object obj,
			OrderInteraction orderInt) throws IOException {
		try {
			response.setContentType("text/html;charset=utf-8");
			response.setCharacterEncoding("utf-8");
			PrintWriter out = response.getWriter();
			out.print(obj);
			out.flush();
			out.close();
			orderInt.setStatus("0");
			orderInt.setOrderInteractionId(String.valueOf(System
					.currentTimeMillis()));
			orderInt.setCreateTime(new Date());
			orderInt.setType("B4");
			int oi1 = orderInteractionService.insert(orderInt);
		} catch (Exception e) {
			orderInt.setOrderInteractionId(String.valueOf(System
					.currentTimeMillis()));
			orderInt.setCreateTime(new Date());
			orderInt.setStatus("1");
			orderInt.setType("B4");
			int oi2 = orderInteractionService.insert(orderInt);
		}
	}

}
